package com.polymathcoder.dpastry.core.network;

import com.polymathcoder.dpastry.api.Service;
import com.polymathcoder.dpastry.api.config.ConfigurationException;
import com.polymathcoder.dpastry.core.config.TcpTransportConfiguration;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by IntelliJ IDEA.
 * User: Drew
 * Date: Jul 7, 2010
 * Time: 11:42:59 AM
 * To change this template use File | Settings | File Templates.
 */
public class TcpTransportService implements Service<TcpTransportConfiguration> {

    boolean running = false;

    protected ChannelFactory channelFactory;
    protected ExecutorService masterThreadPool;
    protected ExecutorService workerThreadPool;
    protected ServerBootstrap bootstrap;
    protected ChannelPipelineFactory pipelineFactory;

    protected ArrayList<InetSocketAddress> bindTargets;
    protected ArrayList<InetSocketAddress> bootstrapNodes;

    public TcpTransportService() {
        //what to do here? anything?
    }

    @Override
    public void initialize(TcpTransportConfiguration cfg) throws ConfigurationException {
        //set up executor services from cfg
        masterThreadPool = Executors.newCachedThreadPool();
        workerThreadPool = Executors.newCachedThreadPool();

        //set up channel factory from cfg (max workers count is 3rd parameter for NioServerSocketChannelFactory
        channelFactory = new NioServerSocketChannelFactory(masterThreadPool, workerThreadPool);

        //set up pipeline factory
        pipelineFactory = new TcpTransportPipelineFactory(cfg.getHandle());

        //set up bootstrap
        bootstrap = new ServerBootstrap(channelFactory);
        bootstrap.setPipelineFactory(pipelineFactory);

        //bootstrap options (get from cfg)
        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);

        //set binding target (get from cfg)
        bindTargets = new ArrayList<InetSocketAddress>(cfg.getIpBindings().size());
        for (TcpTransportConfiguration.IpBinding i : cfg.getIpBindings()) {
            if (i.getAddress() != null) {
                bindTargets.add(new InetSocketAddress(i.getAddress(), i.getPort()));
            } else {
                bindTargets.add(new InetSocketAddress(i.getPort()));
            }
        }

        //set bootstrap nodes (get from cfg)

    }

    @Override
    public boolean start() {
        //set network bindings
        for (InetSocketAddress i : bindTargets) {
            bootstrap.bind(i);
        }
        return running = true;
    }

    @Override
    public boolean stop() {
        //shutdown network
        return running = false;
    }

    @Override
    public boolean isRunning() {
        return running;
    }

    @Override
    public void destroy() {
        //release resources
        //do nothing for the moment
    }

    @Override
    public void forceDestroy() {
        destroy(); //for now, there is no need to differentiate between a "hard" or "soft" destruction
    }
}
